﻿//-----------------------------------------------------------------------
// <copyright file="CompositeStage.cs" author="Artak Mkrtchyan">
//     Creative Commons - GNU General Public License (http://creativecommons.org/licenses/GPL/2.0/
// </copyright>
// <author>Artak Mkrtchyan</author>
// <email>mkArtak@gmail.com</email>
// <date>20/03/2013</date>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace AppUpdateInstaller.Model.InstallationStages
{
	internal sealed class CompositeStage : IInstallationStage
	{
		public event InstallationStageProgressEventHandler ProgressChanged;

		private readonly LinkedList<IInstallationStage> stages;

		public CompositeStage(IEnumerable<IInstallationStage> argStages)
		{
			if (argStages == null)
			{
				throw new ArgumentNullException("argStages");
			}

			this.stages = new LinkedList<IInstallationStage>(argStages);
		}

		public void Run()
		{
			this.ForEachStage(stage => stage.Run());
		}

		public Task RunAsync()
		{
			return Task.Factory.StartNew(this.Run);
		}

		public void RollBack()
		{
			this.ForEachStage(stage =>
			{
				if (stage.SupportsRollback)
				{
					stage.RollBack();
				}
			});
		}

		public Task RollBackAsync()
		{
			return Task.Factory.StartNew(this.RollBack);
		}

		public void FinalizeStage()
		{
			this.ForEachStage(stage =>
			{
				if (stage.HasFinalizerStage)
				{
					stage.FinalizeStage();
				}
			});
		}

		private void ForEachStage(Action<IInstallationStage> argAction)
		{
			LinkedListNode<IInstallationStage> tmpNode = this.stages.First;

			while (tmpNode != null)
			{
				argAction(tmpNode.Value);
				tmpNode = tmpNode.Next;
			}
		}

		public bool SupportsRollback
		{
			get
			{
				return this.stages.Any(item => item.SupportsRollback);
			}
		}

		public bool HasFinalizerStage
		{
			get
			{
				return this.stages.Any(item => item.HasFinalizerStage);
			}
		}
	}
}
